//
//  SpeedTestProc.h
//  GPUProcessingTesting
//
//  Created by kadlubek47 on 17.06.2013.
//  Copyright (c) 2013 kadlubek47. All rights reserved.
//

#include "SpeedTestProc.h"
#include <stdio.h>



#pragma mark INITIALIZE 

SpeedTestProc::SpeedTestProc(): OpenCLProcessorBase("simply_kernels.cl") {
    createKernels();
}

SpeedTestProc::~SpeedTestProc() {
    
    clReleaseMemObject(inBuffer_);
    clReleaseMemObject(outBuffer_);
    clFlush(cmdQueue_);
    
    delete [] data_;
}

void SpeedTestProc::createKernels() {
    inOutKernel_ = clCreateKernel(program_, "in_out", &lastCommandStatus_);
}



#pragma mark BUFFERS

void SpeedTestProc::setBuffers(unsigned int size) {
    if(size == 0)
        throw WrongFunArgVal_Exception();
    
    if(size == buffersLength_)
        return;
    
    if(buffersLength_ != 0) {
        delete [] data_;
        clReleaseMemObject(inBuffer_);
        clReleaseMemObject(outBuffer_);
    }
    
    data_ = new float[size];
    for(int i = 0; i < size; ++i)
        data_[i] = 1;
    
    inBuffer_   = clCreateBuffer(context_, CL_MEM_READ_WRITE, size * sizeof(float), NULL, &lastCommandStatus_);
    outBuffer_  = clCreateBuffer(context_, CL_MEM_READ_WRITE, size * sizeof(float), NULL, &lastCommandStatus_);
    
    lastCommandStatus_  = clEnqueueWriteBuffer(cmdQueue_, inBuffer_, CL_FALSE, 0, size * sizeof(float), data_, 0, NULL, NULL);
    
    lastCommandStatus_  = clSetKernelArg( inOutKernel_, 0, sizeof(cl_mem), &inBuffer_);
	lastCommandStatus_  = clSetKernelArg( inOutKernel_, 1, sizeof(cl_mem), &outBuffer_ );
    
    buffersLength_ = size;
    clFlush(cmdQueue_);
}

void SpeedTestProc::setDataValue(float value) {
    for(int i = 0; i < buffersLength_; ++i)
        data_[i] = value;
}



#pragma mark TRANSFER 

void SpeedTestProc::transferDataToGPU() {
    cl_int lastCommandStatus_;
    lastCommandStatus_ = clEnqueueWriteBuffer( cmdQueue_, inBuffer_, CL_FALSE, 0, buffersLength_ * sizeof(float), data_, 0, NULL, NULL);
}

void SpeedTestProc::transferDataFromGPU(float* destiny) {
    cl_int lastCommandStatus_;
    lastCommandStatus_ = clEnqueueReadBuffer( cmdQueue_, outBuffer_, CL_FALSE, 0, buffersLength_ * sizeof(float), destiny, 0, NULL, NULL);
}

void SpeedTestProc::executeTheSimplestKernel() {
	size_t globalWorkSize[1];
	globalWorkSize[0] = buffersLength_;

    lastCommandStatus_ = clEnqueueNDRangeKernel( cmdQueue_, inOutKernel_, 1, NULL, globalWorkSize, NULL, 0, NULL, NULL);
}